package com.self.av;

import android.Manifest;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PointF;
import android.icu.text.SimpleDateFormat;
import android.media.MediaFormat;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.media3.common.Format;
import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.cache.CacheDataSource;
import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.RenderersFactory;
import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
import androidx.media3.exoplayer.trackselection.TrackSelector;
import androidx.media3.exoplayer.video.VideoFrameMetadataListener;
import androidx.media3.ui.PlayerView;

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;
import com.google.mediapipe.tasks.components.containers.NormalizedLandmark;
import com.google.mediapipe.tasks.core.BaseOptions;
import com.google.mediapipe.tasks.core.Delegate;
import com.google.mediapipe.tasks.core.OutputHandler;
import com.google.mediapipe.tasks.vision.core.RunningMode;
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarker;
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarkerResult;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class VideoCompareActivity extends AppCompatActivity {
    private ExoPlayer player1;
    private ExoPlayer player2;
    private PlayerView playerView1;
    private PlayerView playerView2;
    private ImageView thumbnail1;
    private ImageView thumbnail2;
    private Button selectAllButton;
    private Button settingsButton;
    private PopupWindow popupWindow;
    private Uri videoUri1;
    private Uri videoUri2;
    private HashMap<Integer, List<NormalizedLandmark>> preprocessData1;
    private HashMap<Integer, List<NormalizedLandmark>> preprocessData2;
    private LinearLayout video1LabelContainer;
    private LinearLayout video2LabelContainer;
    private Button deleteButton;
    private Button prevFrameButton;
    private Button nextFrameButton;
    private Button replayStartButton;
    private Button replayButton;
    private Button playButton;
    private TextView video1TextView1;
    private TextView video1TextView2;
    private TextView video1TextView3;
    private TextView video2TextView1;
    private TextView video2TextView2;
    private TextView video2TextView3;
    private SeekBar seekBar;
    private FrameLayout playerViewContainer;
    private ActionLineView actionLineView1;
    private ActionLineView actionLineView2;

    private List<List<NormalizedLandmark>> previousLandmarks1 = new ArrayList<>();
    private List<List<NormalizedLandmark>> previousLandmarks2 = new ArrayList<>();
    private PoseLandmarker poseLandmarker1;
    private PoseLandmarker poseLandmarker2;

    private int video1Selected = 0;
    private int video2Selected = 0;

    private static final float[] speedList = new float[]{0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.1f, 2.2f, 2.3f, 2.4f, 2.5f, 2.6f, 2.7f, 2.8f, 2.9f, 3.0f};
    private int currentSpeed1Idx = 8;
    private int currentSpeed2Idx = 8;

    private boolean isSeekWaiting1 = false;
    private boolean isSeekWaiting2 = false;

    private long replay1StartTime = -1;
    private long replay1EndTime = -1;

    private long replay2StartTime = -1;
    private long replay2EndTime = -1;

    private boolean is1Replay = false;
    private boolean is2Replay = false;



    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;
    private float oldDist = 1f;
    private float scale = 1f;
//    private static final float MIN_SCALE = 1f;
//    private static final float MAX_SCALE = 5f;
    private float lastX = 0;
    private float lastY = 0;
    private float dx = 0;
    private float dy = 0;
    private float initialScale = 1f; // 初始缩放比例
    private float initialTranslationX1 = 0f; // playerView1 初始 X 轴偏移量
    private float initialTranslationY1 = 0f; // playerView1 初始 Y 轴偏移量
    private float initialTranslationX2 = 0f; // playerView2 初始 X 轴偏移量
    private float initialTranslationY2 = 0f; // playerView2 初始 Y 轴偏移量
    private float initialRotationAngle = 0f; // 双指按下时的初始角度
    private float initialRotation = 0f; // 双指按下时视图的初始旋转角度

    private ExecutorService detectionExecutorService;
    private Future<?> currentDetectionTask;
    private HashMap<Integer, Boolean> nodeStates = new HashMap<>();
    private SharedPreferences sharedPreferences;

    private long currentPresentationTimeUs1 = 0;
    private long currentPresentationTimeUs2 = 0;
    private float frameRate1 = 0;
    private float frameRate2 = 0;
    private int totalFrames1 = 0;
    private int totalFrames2 = 0;

    private TextView leftShoulderTextView1;
    private TextView rightShoulderTextView1;
    private TextView leftElbowTextView1;
    private TextView rightElbowTextView1;
    private TextView leftShoulderTextView2;
    private TextView rightShoulderTextView2;
    private TextView leftElbowTextView2;
    private TextView rightElbowTextView2;

    private String selectedModelCompare;

    private static final int[] PAIR_IDS = {
            11, 12
    };


    private final Handler handler = new Handler(Looper.getMainLooper());
//    private final Handler longPressHandler = new Handler(Looper.getMainLooper());

    private final Runnable updateSeekBarRunnable = new Runnable() {
        @Override
        public void run() {
            long currentPosition1 = player1.getCurrentPosition();
            long currentPosition2 = player2.getCurrentPosition();
            long duration1 = player1.getDuration();
            long duration2 = player2.getDuration();
            int progress1 = (int) (((float)currentPosition1 / (float)duration1)  * 100.0f);
            int progress2 = (int) (((float)currentPosition2 / (float)duration2)  * 100.0f);
            if (video1Selected == 1) {
                if (is1Replay && player1.isPlaying()) {
                    if (currentPosition1 >= replay1EndTime){
                        is1Replay = false;
                        player1.pause();
                    }
                }
            }
            if (video2Selected == 1) {
                if (is2Replay && player2.isPlaying()) {
                    if (currentPosition2 >= replay2EndTime){
                        is2Replay = false;
                        player2.pause();
                    }
                }
            }

            if (!(video1Selected == 1 && video2Selected == 1)) {
                if (video1Selected == 1) {
                    seekBar.setProgress(progress1);
                }
                if (video2Selected == 1) {
                    seekBar.setProgress(progress2);
                }
            }
            handler.postDelayed(this, 10); // 每秒更新一次
        }
    };

    private final Runnable forwardRunnable = new Runnable() {
        @OptIn(markerClass = UnstableApi.class) @Override
        public void run() {
            if (video1Selected == 1 && !isSeekWaiting1) {
                isSeekWaiting1 = true;
                long p = player1.getCurrentPosition() + (long) (1000 / player1.getVideoFormat().frameRate);
                player1.seekTo(p);
            }
            if (video2Selected == 1 && !isSeekWaiting2) {
                isSeekWaiting2 = true;
                long p = player2.getCurrentPosition() + (long) (1000 / player2.getVideoFormat().frameRate);
                player2.seekTo(p);
            }
            handler.postDelayed(this, 100); // 每 0.5 秒执行一次
        }
    };

    private final Runnable backwardRunnable = new Runnable() {
        @OptIn(markerClass = UnstableApi.class) @Override
        public void run() {
            if (video1Selected == 1 && !isSeekWaiting1) {
                isSeekWaiting1 = true;
                long p = player1.getCurrentPosition() - (long) (1000 / player1.getVideoFormat().frameRate);
                player1.seekTo(p);
            }
            if (video2Selected == 1 && !isSeekWaiting2) {
                isSeekWaiting2 = true;
                long p = player2.getCurrentPosition() - (long) (1000 / player2.getVideoFormat().frameRate);
                player2.seekTo(p);
            }
            handler.postDelayed(this, 100); // 每 0.5 秒执行一次
        }
    };

    private final Handler checkSharedPrefsHandler = new Handler(Looper.getMainLooper());
    private final Runnable checkSharedPrefsRunnable = new Runnable() {
        @Override
        public void run() {
            boolean shouldProcessFrame = sharedPreferences.getBoolean("shouldProcessFrame", false);
            if (shouldProcessFrame) {
                getNodeState();
                if (videoUri1 != null) {
                    processFrame(1);
                }
                if (videoUri2 != null) {
                    processFrame(2);
                }
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putBoolean("shouldProcessFrame", false); // 重置标记
                editor.apply();
            }
            checkSharedPrefsHandler.postDelayed(this, 100); // 每 100 毫秒检查一次
        }
    };

    // 注册权限请求回调
    private final ActivityResultLauncher<String> requestReadStoragePermissionLauncher =
            registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
                if (isGranted) {
                    // 用户授予了权限，启动选择视频的意图
                    openVideoSelector();
                } else {
                    // 用户拒绝了权限，给出相应提示
                    Toast.makeText(this, "读取外部存储权限被拒绝，无法选择视频", Toast.LENGTH_SHORT).show();
                }
            });

    // 注册启动 Activity 回调
    private final ActivityResultLauncher<Intent> startVideoSelectorLauncher =
            registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
                if (result.getResultCode() == RESULT_OK) {
                    Intent data = result.getData();
                    if (data != null) {
                        Uri uri = data.getData();
                        if (uri != null) {
                            ContentResolver contentResolver = getContentResolver();
                            // 获取文件名
                            String fileName = Utils.getFileName(contentResolver, uri);
                            // 根据请求码判断是哪个缩略图触发的选择
                            if (video1Selected == 1) {
                                videoUri1 = uri;
                                setVideoAndThumbnail(videoUri1, player1, thumbnail1);
                                preprocessData1 = Utils.loadPreprocessData(getApplicationContext(), videoUri1);
                                if (preprocessData1.size() > 0) {
                                    runOnUiThread(() -> Toast.makeText(this, "视频1加载预处理", Toast.LENGTH_SHORT).show());
                                }
                                long videoTakenTime = getVideoTakenOrCreatedTime(videoUri1);
                                if (videoTakenTime != -1) {
                                    video1TextView1.setText(formatDate(videoTakenTime));
                                }
                            } else if (video2Selected == 1) {
                                videoUri2 = uri;
                                setVideoAndThumbnail(videoUri2, player2, thumbnail2);
                                preprocessData2 = Utils.loadPreprocessData(getApplicationContext(), videoUri2);
                                if (preprocessData2.size() > 0) {
                                    runOnUiThread(() -> Toast.makeText(this, "视频2加载预处理", Toast.LENGTH_SHORT).show());
                                }
                                long videoTakenTime = getVideoTakenOrCreatedTime(videoUri2);
                                if (videoTakenTime != -1) {
                                    video2TextView1.setText(formatDate(videoTakenTime));
                                }
                            }
                        }
                    }
                }
            });


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String selectedModel = getIntent().getStringExtra("selectedModel");
        sharedPreferences = getSharedPreferences("VideoPlayerPrefs", MODE_PRIVATE);
        selectedModelCompare = getIntent().getStringExtra("selectedModelCompare");
        sharedPreferences = getSharedPreferences("VideoPlayerPrefs", MODE_PRIVATE);

        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString("selectedModel", selectedModel);
        editor.putString("selectedModelCompare", selectedModelCompare);
        editor.apply();

        if (selectedModelCompare.equals("上下")) {
            setContentView(R.layout.activity_video_compare2);
        } else {
            setContentView(R.layout.activity_video_compare);
        }

        nodeStates.put(0, true);
        nodeStates.put(11, true);
        nodeStates.put(12, true);
        nodeStates.put(13, true);
        nodeStates.put(14, true);
        nodeStates.put(15, true);
        nodeStates.put(16, true);
        nodeStates.put(23, true);
        nodeStates.put(24, true);

        detectionExecutorService = Executors.newFixedThreadPool(8);

        getNodeState();
        loadMPModel(selectedModel);
        // 初始化视图
        initViews();
        // 初始化播放器
        initPlayers();

        // 记录初始状态
        initialTranslationX1 = playerView1.getTranslationX();
        initialTranslationY1 = playerView1.getTranslationY();
        initialTranslationX2 = playerView2.getTranslationX();
        initialTranslationY2 = playerView2.getTranslationY();
        initialScale = 1f; // 初始缩放比例，假设初始为 1
        initialRotation = 0f; // 初始旋转角度，假设初始为 0

        playerViewContainer.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                handleTouchEvent(event);
                return true;
            }
        });

        thumbnail1.setOnClickListener(v -> {
            // 打开视频选择器
            selectVideo1();
            if (videoUri1 == null) {
                String permission = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
                        ? Manifest.permission.READ_MEDIA_VIDEO
                        : Manifest.permission.READ_EXTERNAL_STORAGE;
                // 检查是否已经授予读取外部存储的权限
                if (ContextCompat.checkSelfPermission(VideoCompareActivity.this, permission)
                        != PackageManager.PERMISSION_GRANTED) {
                    // 如果没有授予权限，则请求权限
                    requestReadStoragePermissionLauncher.launch(permission);
                } else {
                    openVideoSelector();
                }
            }
        });

        thumbnail2.setOnClickListener(v -> {
            // 打开视频选择器
            selectVideo2();
            if (videoUri2 == null) {
                String permission = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
                        ? Manifest.permission.READ_MEDIA_VIDEO
                        : Manifest.permission.READ_EXTERNAL_STORAGE;
                // 检查是否已经授予读取外部存储的权限
                if (ContextCompat.checkSelfPermission(VideoCompareActivity.this, permission)
                        != PackageManager.PERMISSION_GRANTED) {
                    // 如果没有授予权限，则请求权限
                    requestReadStoragePermissionLauncher.launch(permission);
                } else {
                    openVideoSelector();
                }
            }
        });

        // 全选按钮点击事件
        selectAllButton.setOnClickListener(v -> {
            video1Selected = 1;
            video2Selected = 1;
            video1LabelContainer.setBackgroundColor(Color.BLUE);
            video2LabelContainer.setBackgroundColor(Color.BLUE);
            replayStartButton.setEnabled(false);
            playerView1.setVisibility(View.VISIBLE);
            playerView2.setVisibility(View.VISIBLE);
            if (!selectedModelCompare.equals("上下")) {
                playerView2.setAlpha(0.5f);
            }
            seekBar.setVisibility(View.GONE);
            player1.pause();
            player2.pause();
            video1TextView2.setText("暂停：" + video1TextView2.getText().toString().split("：")[1]);
            video2TextView2.setText("暂停：" + video2TextView2.getText().toString().split("：")[1]);
        });

        // 删除按钮点击事件
        deleteButton.setOnClickListener(v -> {
            if (video1Selected == 1) {
                videoUri1 = null;
                thumbnail1.setImageResource(R.drawable.select_video);
                video1Selected = 0;
                video1LabelContainer.setBackgroundColor(Color.TRANSPARENT);
                video1TextView1.setText("视频1");
                video1TextView2.setText("暂停：1.0x");
                video1TextView3.setText("回放：-1ms --> -1ms");
            }
            if (video2Selected == 1) {
                videoUri2 = null;
                thumbnail2.setImageResource(R.drawable.select_video);
                video2Selected = 0;
                video2LabelContainer.setBackgroundColor(Color.TRANSPARENT);
                video2TextView1.setText("视频2");
                video2TextView2.setText("暂停：1.0x");
                video2TextView3.setText("回放：-1ms --> -1ms");
            }
            replayStartButton.setEnabled(true);
        });

        // 上一帧按钮点击事件
        prevFrameButton.setOnClickListener(v -> {
            if (video1Selected == 1) {
                long p = player1.getCurrentPosition() - (long)(1000 / player1.getVideoFormat().frameRate);
                player1.seekTo(p); // 回退 1 秒
            }
            if (video2Selected == 1) {
                long p = player2.getCurrentPosition() - (long)(1000 / player2.getVideoFormat().frameRate);
                player2.seekTo(p); // 回退 1 秒
            }
        });
        prevFrameButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                handler.post(backwardRunnable);
                return true;
            }
        });
        prevFrameButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
                    handler.removeCallbacks(backwardRunnable);
                }
                return false;
            }
        });

        // 下一帧按钮点击事件
        nextFrameButton.setOnClickListener(v -> {
            if (video1Selected == 1) {
                long p = player1.getCurrentPosition() + (long)(1000 / player1.getVideoFormat().frameRate);
                player1.seekTo(p); // 前进 1 秒
            }
            if (video2Selected == 1) {
                long p = player2.getCurrentPosition() + (long)(1000 / player2.getVideoFormat().frameRate);
                player2.seekTo(p); // 前进 1 秒
            }
        });
        nextFrameButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                handler.post(forwardRunnable);
                return true;
            }
        });
        nextFrameButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
                    handler.removeCallbacks(forwardRunnable);
                }
                return false;
            }
        });


        // 回放起点按钮点击事件
        replayStartButton.setOnClickListener(v -> {
            if (video1Selected == 1) {
                if (replayStartButton.getText().equals("清除")){
                    replay1StartTime = -1;
                    replay1EndTime = -1;
                    replayStartButton.setText("起点");
                    replayButton.setEnabled(false);
                } else {
                    long currentPosition = player1.getCurrentPosition();
                    if (currentPosition <= replay1StartTime) {
                        replay1StartTime = -1;
                    }
                    if (replay1StartTime == -1) {
                        replay1StartTime = currentPosition;
                        replayStartButton.setText("终点");
                    } else if (replay1EndTime == -1) {
                        replay1EndTime = currentPosition;
                        replayStartButton.setText("清除");
                        replayButton.setEnabled(true);
                    }
                }
                video1TextView3.setText("回放：" + replay1StartTime + "ms --> " + replay1EndTime + "ms");
            }
            if (video2Selected == 1) {
                if (replayStartButton.getText().equals("清除")){
                    replay2StartTime = -1;
                    replay2EndTime = -1;
                    replayStartButton.setText("起点");
                    replayButton.setEnabled(false);
                } else {
                    long currentPosition = player2.getCurrentPosition();
                    if (currentPosition <= replay2StartTime) {
                        replay2StartTime = -1;
                    }
                    if (replay2StartTime == -1) {
                        replay2StartTime = currentPosition;
                        replayStartButton.setText("终点");
                    } else if (replay2EndTime == -1) {
                        replay2EndTime = currentPosition;
                        replayStartButton.setText("清除");
                        replayButton.setEnabled(true);
                    }
                }
                video2TextView3.setText("回放：" + replay2StartTime + "ms --> " + replay2EndTime + "ms");
            }
        });

        // 回放按钮点击事件
        replayButton.setOnClickListener(v -> {
            if (video1Selected == 1) {
                if (replay1StartTime != -1 && replay1EndTime != -1) {
                    is1Replay = true;
                    player1.pause();
                    player1.seekTo(replay1StartTime);
                    player1.play();
                }
            }
            if (video2Selected == 1) {
                if (replay2StartTime != -1 && replay2EndTime != -1) {
                    is2Replay = true;
                    player2.pause();
                    player2.seekTo(replay2StartTime);
                    player2.play();
                }
            }
        });

        // 播放按钮点击事件
        playButton.setOnClickListener(v -> {
            if (video1Selected == 1 && video2Selected == 1 && (player1.isPlaying() || player2.isPlaying())){
                player1.pause();
                video1TextView2.setText("暂停：" + video1TextView2.getText().toString().split("：")[1]);
                player2.pause();
                video2TextView2.setText("暂停：" + video2TextView2.getText().toString().split("：")[1]);
            } else {
                if (video1Selected == 1) {
                    if (player1.isPlaying()) {
                        player1.pause();
                        video1TextView2.setText("暂停：" + video1TextView2.getText().toString().split("：")[1]);
                    } else {
                        if (player1.getCurrentPosition() >= player1.getDuration()) {
                            player1.seekTo(0);
                        }
                        player1.play();
                        video1TextView2.setText("播放：" + video1TextView2.getText().toString().split("：")[1]);
                    }
                }
                if (video2Selected == 1) {
                    if (player2.isPlaying()) {
                        player2.pause();
                        video2TextView2.setText("暂停：" + video2TextView2.getText().toString().split("：")[1]);
                    } else {
                        if (player2.getCurrentPosition() >= player2.getDuration()) {
                            player2.seekTo(0);
                        }
                        player2.play();
                        video2TextView2.setText("播放：" + video2TextView2.getText().toString().split("：")[1]);
                    }
                }
            }
        });

        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser) {
                    if (video1Selected == 1) {
                        long duration1 = player1.getDuration();
                        long position = (long) ((float) duration1 * ((float) progress / 100.0f));
                        player1.seekTo(position);
                    }
                    if (video2Selected == 1) {
                        long duration2 = player2.getDuration();
                        long position = (long) ((float) duration2 * ((float) progress / 100.0f));
                        player2.seekTo(position);
                    }
                }
            }
//                handler.post(updateSeekBarRunnable);

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                player1.pause();
                player2.pause();
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                if (video1Selected == 1 && video1TextView2.getText().toString().indexOf("播放") > 0) {
                    player1.play();
                }
                if (video2Selected == 1 && video2TextView2.getText().toString().indexOf("播放") > 0) {
                    player2.play();
                }
//                processFrame();
//                handler.post(updateSeekBarRunnable);
            }
        });

        settingsButton.setOnClickListener(v -> {
            if (popupWindow.isShowing()) {
                popupWindow.dismiss();
            } else {
                // 获取屏幕宽度
                int screenWidth = getResources().getDisplayMetrics().widthPixels;
                // 计算 x 偏移量，使 PopupWindow 从右上角弹出
                int xOffset = screenWidth - popupWindow.getWidth();
                // 显示 PopupWindow，从右上角弹出
                popupWindow.showAtLocation(v, Gravity.TOP | Gravity.END, 0, 0);
            }
        });

        View popupView = LayoutInflater.from(this).inflate(R.layout.popup_menu_compare, null);
        Button customNodeButton = popupView.findViewById(R.id.customNodeButton);
        Button resetButton = popupView.findViewById(R.id.resetButton);
        Button decreaseSpeedButton = popupView.findViewById(R.id.decreaseSpeedButton);
        Button increaseSpeedButton = popupView.findViewById(R.id.increaseSpeedButton);

        customNodeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popupWindow.dismiss();
                // 启动 CustomNodeActivity
                Intent intent = new Intent(VideoCompareActivity.this, CustomNodeActivity.class);
                startActivity(intent);
            }
        });

        resetButton.setOnClickListener(v -> {
            if (video1Selected == 1) {
                currentSpeed1Idx = 8;
                float newRate1 = speedList[currentSpeed1Idx];
                player1.setPlaybackParameters(new PlaybackParameters(newRate1));
                video1TextView2.setText(video1TextView2.getText().toString().split("：")[0] + "：" + speedList[currentSpeed1Idx] + "x");
                // 重置 playerView1 的位置、缩放和旋转
                playerView1.setTranslationX(initialTranslationX1);
                playerView1.setTranslationY(initialTranslationY1);
                playerView1.setScaleX(initialScale);
                playerView1.setScaleY(initialScale);
                playerView1.setRotation(0f);
            }
            if (video2Selected == 1) {
                currentSpeed2Idx = 8;
                float newRate2 = speedList[currentSpeed2Idx];
                player2.setPlaybackParameters(new PlaybackParameters(newRate2));
                video2TextView2.setText(video2TextView2.getText().toString().split("：")[0] + "：" + speedList[currentSpeed2Idx] + "x");
                // 重置 playerView2 的位置、缩放和旋转
                playerView2.setTranslationX(initialTranslationX2);
                playerView2.setTranslationY(initialTranslationY2);
                playerView2.setScaleX(initialScale);
                playerView2.setScaleY(initialScale);
                playerView2.setRotation(0f);
            }
        });

        decreaseSpeedButton.setOnClickListener(v -> {
            if (video1Selected == 1) {
                currentSpeed1Idx = Math.max(currentSpeed1Idx - 1, 0);
                float newRate1 = speedList[currentSpeed1Idx];
                player1.setPlaybackParameters(new PlaybackParameters(newRate1));
                video1TextView2.setText(video1TextView2.getText().toString().split("：")[0] + "：" + speedList[currentSpeed1Idx] + "x");
            }
            if (video2Selected == 1) {
                currentSpeed2Idx = Math.max(currentSpeed2Idx - 1, 0);
                float newRate2 = speedList[currentSpeed2Idx];
                player2.setPlaybackParameters(new PlaybackParameters(newRate2));
                video2TextView2.setText(video1TextView2.getText().toString().split("：")[0] + "：" + speedList[currentSpeed2Idx] + "x");
            }
        });

        increaseSpeedButton.setOnClickListener(v -> {
            if (video1Selected == 1) {
                currentSpeed1Idx = Math.min(currentSpeed1Idx + 1, speedList.length - 1);
                float newRate1 = speedList[currentSpeed1Idx];
                player1.setPlaybackParameters(new PlaybackParameters(newRate1));
                video1TextView2.setText(video1TextView2.getText().toString().split("：")[0] + "：" + speedList[currentSpeed1Idx] + "x");
            }
            if (video2Selected == 1) {
                currentSpeed2Idx = Math.min(currentSpeed2Idx + 1, speedList.length - 1);
                float newRate2 = speedList[currentSpeed2Idx];
                player2.setPlaybackParameters(new PlaybackParameters(newRate2));
                video2TextView2.setText(video1TextView2.getText().toString().split("：")[0] + "：" + speedList[currentSpeed2Idx] + "x");
            }
        });

        popupWindow = new PopupWindow(
                popupView,
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                true
        );
        popupWindow.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.dialog_holo_light_frame));
        popupWindow.setOutsideTouchable(true);

        // 开始更新 SeekBar
        handler.post(updateSeekBarRunnable);
        handler.post(checkSharedPrefsRunnable);

    }

    private void selectVideo1() {
        video1Selected = 1;
        video2Selected = 0;
        video1LabelContainer.setBackgroundColor(Color.BLUE);
        video2LabelContainer.setBackgroundColor(Color.TRANSPARENT);
        replayStartButton.setEnabled(true);
        seekBar.setVisibility(View.VISIBLE);
        playerView1.setVisibility(View.VISIBLE);
        if (!selectedModelCompare.equals("上下")) {
            playerView2.setVisibility(View.GONE);
        }
        player1.pause();
        player2.pause();
        video1TextView2.setText("暂停：" + video1TextView2.getText().toString().split("：")[1]);
        video2TextView2.setText("暂停：" + video2TextView2.getText().toString().split("：")[1]);
        if (replay1StartTime != -1 && replay1EndTime != -1) {
            replayStartButton.setText("清除");
            replayButton.setEnabled(true);
        } else if (replay1StartTime == -1) {
            replayStartButton.setText("起点");
            replayButton.setEnabled(false);
        } else if (replay1EndTime == -1) {
            replayStartButton.setText("终点");
            replayButton.setEnabled(false);
        }
    }

    private void selectVideo2() {
        video1Selected = 0;
        video2Selected = 1;
        video2LabelContainer.setBackgroundColor(Color.BLUE);
        video1LabelContainer.setBackgroundColor(Color.TRANSPARENT);
        replayStartButton.setEnabled(true);
        seekBar.setVisibility(View.VISIBLE);
        if (!selectedModelCompare.equals("上下")) {
            playerView1.setVisibility(View.GONE);
        }
        playerView2.setVisibility(View.VISIBLE);
        playerView2.setAlpha(1.0f);
        player1.pause();
        player2.pause();
        video1TextView2.setText("暂停：" + video1TextView2.getText().toString().split("：")[1]);
        video2TextView2.setText("暂停：" + video2TextView2.getText().toString().split("：")[1]);
        if (replay2StartTime != -1 && replay2EndTime != -1) {
            replayStartButton.setText("清除");
            replayButton.setEnabled(true);
        } else if (replay2StartTime == -1) {
            replayStartButton.setText("起点");
            replayButton.setEnabled(false);
        } else if (replay2EndTime == -1) {
            replayStartButton.setText("终点");
            replayButton.setEnabled(false);
        }
    }

    private void initViews() {
        thumbnail1 = findViewById(R.id.thumbnail1);
        thumbnail2 = findViewById(R.id.thumbnail2);
        selectAllButton = findViewById(R.id.selectAllButton);
        video1LabelContainer = findViewById(R.id.video1LabelContainer);
        video2LabelContainer = findViewById(R.id.video2LabelContainer);
        deleteButton = findViewById(R.id.deleteButton);
        prevFrameButton = findViewById(R.id.prevFrameButton);
        nextFrameButton = findViewById(R.id.nextFrameButton);
        replayStartButton = findViewById(R.id.replayStartButton);
        replayButton = findViewById(R.id.replayButton);
        playButton = findViewById(R.id.playButton);
        video1TextView1 = findViewById(R.id.video1TextView1);
        video1TextView2 = findViewById(R.id.video1TextView2);
        video1TextView3 = findViewById(R.id.video1TextView3);
        video2TextView1 = findViewById(R.id.video2TextView1);
        video2TextView2 = findViewById(R.id.video2TextView2);
        video2TextView3 = findViewById(R.id.video2TextView3);
        seekBar = findViewById(R.id.seekBar);
        playerViewContainer = findViewById(R.id.playerViewContainer);
        actionLineView1 = findViewById(R.id.actionLineView1);
        actionLineView2 = findViewById(R.id.actionLineView2);
        settingsButton = findViewById(R.id.settingsButton);
        leftShoulderTextView1 = findViewById(R.id.leftShoulderTextView1);
        rightShoulderTextView1 = findViewById(R.id.rightShoulderTextView1);
        leftElbowTextView1 = findViewById(R.id.leftElbowTextView1);
        rightElbowTextView1 = findViewById(R.id.rightElbowTextView1);
        leftShoulderTextView2 = findViewById(R.id.leftShoulderTextView2);
        rightShoulderTextView2 = findViewById(R.id.rightShoulderTextView2);
        leftElbowTextView2 = findViewById(R.id.leftElbowTextView2);
        rightElbowTextView2 = findViewById(R.id.rightElbowTextView2);
    }

    private void initPlayers() {
        RenderersFactory renderersFactory = new DefaultRenderersFactory(this)
                .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER);
        TrackSelector trackSelector = new DefaultTrackSelector(getApplicationContext());
        TrackSelectionParameters trackParams = new TrackSelectionParameters.Builder(getApplicationContext())
                .setMaxVideoSize(1920, 1080)
                .build();
        trackSelector.setParameters(trackParams);
        player1 = new ExoPlayer.Builder(this)
                .setRenderersFactory(renderersFactory)
                .setTrackSelector(trackSelector)
                .setUsePlatformDiagnostics(false)
                .build();
        player2 = new ExoPlayer.Builder(this)
                .setRenderersFactory(renderersFactory)
                .setTrackSelector(trackSelector)
                .setUsePlatformDiagnostics(false)
                .build();
        playerView1 = findViewById(R.id.playerView1);
        playerView2 = findViewById(R.id.playerView2);
        playerView1.setPlayer(player1);
        playerView2.setPlayer(player2);
        player1.addListener(new Player.Listener() {
            @Override
            public void onPlaybackStateChanged(int playbackState) {
                if (playbackState == Player.STATE_READY) {
                    long durationMs = player1.getDuration();
                    frameRate1 = player1.getVideoFormat().frameRate;
                    totalFrames1 = (int) (durationMs * frameRate1 / 1000); // 总帧数

                    if (preprocessData1.size() != totalFrames1) {
                        preprocessData1 = Utils.loadPreprocessData(getApplicationContext(), videoUri1);
                    }
                }
                if (playbackState == Player.EVENT_IS_LOADING_CHANGED) {
                    isSeekWaiting1 = false;
                }
                if (playbackState == Player.STATE_ENDED) {
                    player1.pause();
                    video1TextView2.setText("暂停：" + video1TextView2.getText().toString().split("：")[1]);
                }
                Player.Listener.super.onPlaybackStateChanged(playbackState);
            }
        });
        player2.addListener(new Player.Listener() {
            @Override
            public void onPlaybackStateChanged(int playbackState) {
                if (playbackState == Player.STATE_READY) {
                    long durationMs = player2.getDuration();
                    frameRate2 = player2.getVideoFormat().frameRate;
                    totalFrames2 = (int) (durationMs * frameRate2 / 1000); // 总帧数

                    if (preprocessData2.size() != totalFrames2) {
                        preprocessData2 = Utils.loadPreprocessData(getApplicationContext(), videoUri2);
                    }
                }
                if (playbackState == Player.EVENT_IS_LOADING_CHANGED) {
                    isSeekWaiting2 = false;
                }
                if (playbackState == Player.STATE_ENDED) {
                    player2.pause();
                    video2TextView2.setText("暂停：" + video2TextView2.getText().toString().split("：")[1]);
                }
                Player.Listener.super.onPlaybackStateChanged(playbackState);
            }
        });
        player1.setVideoFrameMetadataListener(new VideoFrameMetadataListener() {
            @Override
            public void onVideoFrameAboutToBeRendered(long presentationTimeUs, long releaseTimeNs, Format format, @Nullable MediaFormat mediaFormat) {
                currentPresentationTimeUs1 = presentationTimeUs;
                if (currentDetectionTask != null && !currentDetectionTask.isDone()) {
                    currentDetectionTask.cancel(true);
                }
                currentDetectionTask = detectionExecutorService.submit(() -> {
                    if (!Thread.currentThread().isInterrupted()) {
                        processFrame(1);
                    }
                });
            }
        });

        player2.setVideoFrameMetadataListener(new VideoFrameMetadataListener() {
            @Override
            public void onVideoFrameAboutToBeRendered(long presentationTimeUs, long releaseTimeNs, Format format, @Nullable MediaFormat mediaFormat) {
                currentPresentationTimeUs2 = presentationTimeUs;
                if (currentDetectionTask != null && !currentDetectionTask.isDone()) {
                    currentDetectionTask.cancel(true);
                }
                currentDetectionTask = detectionExecutorService.submit(() -> {
                    if (!Thread.currentThread().isInterrupted()) {
                        processFrame(2);
                    }
                });
            }
        });
    }

    private void openVideoSelector() {
        // 使用 Intent.ACTION_PICK 打开系统相册选择视频
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("video/*");
        startVideoSelectorLauncher.launch(intent);
    }

    private void setVideoAndThumbnail(Uri videoUri, ExoPlayer player, ImageView thumbnail) {
        MediaItem mediaItem = MediaItem.fromUri(videoUri);
        CacheDataSource.Factory cacheDataSourceFactory = CacheManager.getCacheDataSourceFactory(this);
        MediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
                .createMediaSource(mediaItem);
        player.setMediaSource(mediaSource);
        player.prepare();

        // 获取视频缩略图p
        Bitmap thumbnailBitmap = getVideoThumbnail(videoUri);
        if (thumbnailBitmap != null) {
            thumbnail.setImageBitmap(thumbnailBitmap);
        }
    }

    private Bitmap getVideoThumbnail(Uri uri) {
        String[] projection = {MediaStore.Video.Media.DATA};
        Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            String filePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
            cursor.close();
            return ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Images.Thumbnails.MINI_KIND);
        }
        return null;
    }




    private void handleTouchEvent(MotionEvent event) {
        PlayerView playerView = null;
        if (video2Selected == 1) {
            playerView = playerView2;
        } else if (video1Selected == 1) {
            playerView = playerView1;
        }
        if (playerView == null) {
            return;
        }
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                lastX = event.getX();
                lastY = event.getY();
                mode = DRAG;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                oldDist = spacing(event);
                if (oldDist > 10f) {
                    mode = ZOOM;
                    // 更新初始旋转角度和视图初始旋转角度
                    initialRotationAngle = getVectorAngle(event);
                    initialRotation = playerView.getRotation();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (event.getPointerCount() == 2) {
                    if (mode == ZOOM) {
                        float newDist = spacing(event);
                        if (newDist > 10f) {
                            float newScale = scale * (newDist / oldDist);
                            // 限制缩放范围
                            newScale = Math.max(0.5f, Math.min(newScale, 5f));
                            scale = newScale;
                            scaleViews(playerView, scale);
                            oldDist = newDist;
                        }

                        // 处理旋转逻辑
                        float currentRotationAngle = getVectorAngle(event);
                        float deltaRotation = currentRotationAngle - initialRotationAngle;
                        float newRotation = initialRotation + deltaRotation;
                        rotateViews(playerView, newRotation);
                    }
                } else if (mode == DRAG) {
                    dx = event.getX() - lastX;
                    dy = event.getY() - lastY;
                    moveViews(playerView, dx, dy);
                    lastX = event.getX();
                    lastY = event.getY();
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
        }
    }

    // 计算双指向量的角度
    private float getVectorAngle(MotionEvent event) {
        if (event.getPointerCount() < 2) {
            return 0;
        }
        float x1 = event.getX(0);
        float y1 = event.getY(0);
        float x2 = event.getX(1);
        float y2 = event.getY(1);

        float dx = x2 - x1;
        float dy = y2 - y1;

        return (float) Math.toDegrees(Math.atan2(dy, dx));
    }

    // 旋转视图的方法
    private void rotateViews(PlayerView playerView, float rotation) {
        playerView.setRotation(rotation);
    }

    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }

    private void moveViews(PlayerView playerView, float dx, float dy) {
        playerView.setTranslationX(playerView.getTranslationX() + dx);
        playerView.setTranslationY(playerView.getTranslationY() + dy);
    }

    private void scaleViews(PlayerView playerView, float scale) {
        playerView.setScaleX(scale);
        playerView.setScaleY(scale);
    }



    private long getVideoTakenOrCreatedTime(Uri uri) {
        String[] projection = {
                MediaStore.Video.Media.DATE_TAKEN,
                MediaStore.Video.Media.DATE_ADDED
        };
        Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            int dateTakenColumnIndex = cursor.getColumnIndex(MediaStore.Video.Media.DATE_TAKEN);
            int dateAddedColumnIndex = cursor.getColumnIndex(MediaStore.Video.Media.DATE_ADDED);

            long dateTaken = cursor.getLong(dateTakenColumnIndex);
            long dateAdded = cursor.getLong(dateAddedColumnIndex) * 1000; // DATE_ADDED 单位为秒，转换为毫秒

            // 优先使用拍摄时间
            if (dateTaken > 0) {
                cursor.close();
                return dateTaken;
            } else if (dateAdded > 0) {
                cursor.close();
                return dateAdded;
            }
            cursor.close();
        }
        return -1;
    }

    // 可选：格式化时间的方法
    private String formatDate(long timeInMillis) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
        return sdf.format(new Date(timeInMillis));
    }


    private void processFrame(int playerId) {
        int totalFrames = 0;
        float frameRate = 0;
        long currentPresentationTimeUs = 0;
        Player player = null;
        PlayerView playerView = null;
        ActionLineView actionLineView = null;
        HashMap<Integer, List<NormalizedLandmark>> preprocessData = new HashMap<>();
        PoseLandmarker poseLandmarker = null;
        if (playerId == 1) {
            totalFrames = totalFrames1;
            frameRate = frameRate1;
            currentPresentationTimeUs = currentPresentationTimeUs1;
            preprocessData = preprocessData1;
            actionLineView = actionLineView1;
            player = player1;
            playerView = playerView1;
            poseLandmarker = poseLandmarker1;
        } else {
            totalFrames = totalFrames2;
            frameRate = frameRate2;
            currentPresentationTimeUs = currentPresentationTimeUs2;
            preprocessData = preprocessData2;
            actionLineView = actionLineView2;
            player = player2;
            playerView = playerView2;
            poseLandmarker = poseLandmarker2;
        }
        if (preprocessData.size() > 0) {
            int frameIndex = -1;
            if (player != null) {
                try {
                    frameIndex = (int)(currentPresentationTimeUs * frameRate / 1000000); // 核心计算公式
                    frameIndex = Math.max(0, Math.min(frameIndex, totalFrames - 1)); // 限制范围
                    // 示例：使用帧数获取预处理数据
                    List<NormalizedLandmark> preprocessLandmarks = preprocessData.get(frameIndex);
                    if (preprocessLandmarks != null) {
                        // 可在此处使用预处理的坐标数据（如绘制、计算等）
                        processLandmarkers(playerId, preprocessLandmarks);
                    }
                    actionLineView.invalidate();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else {
            Bitmap frame = ((TextureView) playerView.getVideoSurfaceView()).getBitmap();
            if (frame != null) {
                MPImage mpImage = new BitmapImageBuilder(frame).build();
                poseLandmarker.detectAsync(mpImage, SystemClock.uptimeMillis());

            }
        }
    }

    public void loadMPModel(String selectedModel) {
        // 模型文件在assets目录下的文件名
        String modelName = String.format("pose_landmarker_%s.task", selectedModel);
        BaseOptions.Builder baseOptionsBuilder = BaseOptions.builder();
        baseOptionsBuilder.setDelegate(Delegate.GPU);
        baseOptionsBuilder.setModelAssetPath(modelName);
        PoseLandmarker.PoseLandmarkerOptions.Builder optionsBuilder = PoseLandmarker.PoseLandmarkerOptions.builder();
        OutputHandler.ResultListener<PoseLandmarkerResult, MPImage> returnLivestreamResult1 = new OutputHandler.ResultListener<PoseLandmarkerResult, MPImage>() {
            @Override
            public void run(PoseLandmarkerResult result, MPImage input) {
                List<List<NormalizedLandmark>> landmarks_lst = result.landmarks();
                landmarks_lst = Utils.applyFilter(previousLandmarks1, landmarks_lst);
                for (List<NormalizedLandmark> landmarks : landmarks_lst) {
                    processLandmarkers(1, landmarks);
                }
                actionLineView1.invalidate();
            }
        };
        optionsBuilder.setBaseOptions(baseOptionsBuilder.build())
                .setMinPoseDetectionConfidence(0.8f)
                .setMinTrackingConfidence(0.9f)
                .setMinPosePresenceConfidence(0.8f)
                .setNumPoses(1)
                .setOutputSegmentationMasks(false)
                .setResultListener(returnLivestreamResult1)
                .setRunningMode(RunningMode.LIVE_STREAM);
        PoseLandmarker.PoseLandmarkerOptions poseLandmarkerOptions1 = optionsBuilder.build();
        poseLandmarker1 = PoseLandmarker.createFromOptions(getApplicationContext(), poseLandmarkerOptions1);

        OutputHandler.ResultListener<PoseLandmarkerResult, MPImage> returnLivestreamResult2 = new OutputHandler.ResultListener<PoseLandmarkerResult, MPImage>() {
            @Override
            public void run(PoseLandmarkerResult result, MPImage input) {
                List<List<NormalizedLandmark>> landmarks_lst = result.landmarks();
                landmarks_lst = Utils.applyFilter(previousLandmarks2, landmarks_lst);
                for (List<NormalizedLandmark> landmarks : landmarks_lst) {
                    processLandmarkers(2, landmarks);
                }
                actionLineView2.invalidate();
            }
        };
        optionsBuilder.setBaseOptions(baseOptionsBuilder.build())
                .setMinPoseDetectionConfidence(0.8f)
                .setMinTrackingConfidence(0.9f)
                .setMinPosePresenceConfidence(0.8f)
                .setNumPoses(1)
                .setOutputSegmentationMasks(false)
                .setResultListener(returnLivestreamResult2)
                .setRunningMode(RunningMode.LIVE_STREAM);
        PoseLandmarker.PoseLandmarkerOptions poseLandmarkerOptions2 = optionsBuilder.build();
        poseLandmarker2 = PoseLandmarker.createFromOptions(getApplicationContext(), poseLandmarkerOptions2);
    }

    private void processLandmarkers(int playerId, List<NormalizedLandmark> landmarks){
        ActionLineView actionLineView = playerId == 1 ? actionLineView1 : actionLineView2;

        List<PointF> jointPoints = convertLandmarkToJointPoints(landmarks, playerId);
        List<PointF[]> lines = convertLandmarkToLines(landmarks, playerId);
//        List<PointF> pathPoints = convertLandmarkToPathPoints(landmarks, playerId);
        actionLineView.setCircles(jointPoints);
        actionLineView.setLines(lines);
//        actionLineView.addPathPoints(pathPoints);

        if (landmarks.size() > 16) { // 确保关键点索引有效
            PointF p11 = getJointPosition(landmarks.get(11), playerId); // 左肩
            PointF p12 = getJointPosition(landmarks.get(12), playerId); // 右肩
            PointF p13 = getJointPosition(landmarks.get(13), playerId); // 左肘
            PointF p14 = getJointPosition(landmarks.get(14), playerId); // 右肘
            PointF p15 = getJointPosition(landmarks.get(15), playerId); // 左手腕
            PointF p16 = getJointPosition(landmarks.get(16), playerId); // 右手腕

            // 计算各角度
            double angle1 = Utils.calculateAngle(p12, p11, p13); // {11, 12}和{11, 13}的角度
            if (p13.y > p11.y) {
                angle1 = 360 - angle1;
            }
            double angle2 = Utils.calculateAngle(p11, p12, p14); // {11, 12}和{12, 14}的角度
            if (p14.y > p12.y) {
                angle2 = 360 - angle2;
            }
            double angle3 = Utils.calculateAngle(p11, p13, p15); // {11, 13}和{13, 15}的夹角
            double angle4 = Utils.calculateAngle(p12, p14, p16); // {12, 14}和{14, 16}的夹角
            double finalAngle = angle1;
            double finalAngle1 = angle2;
            if (playerId == 1) {
                runOnUiThread(() -> {
                    leftShoulderTextView1.setText(String.format("%.2f°", finalAngle));
                    rightShoulderTextView1.setText(String.format("%.2f°", finalAngle1));
                    leftElbowTextView1.setText(String.format("%.2f°", angle3));
                    rightElbowTextView1.setText(String.format("%.2f°", angle4));
                });
            } else {
                runOnUiThread(() -> {
                    leftShoulderTextView2.setText(String.format("%.2f°", finalAngle));
                    rightShoulderTextView2.setText(String.format("%.2f°", finalAngle1));
                    leftElbowTextView2.setText(String.format("%.2f°", angle3));
                    rightElbowTextView2.setText(String.format("%.2f°", angle4));
                });
            }

            // 可以在这里使用角度值，例如打印日志或传递给视图显示
//            Log.d("AngleCalculation", String.format(
//                    "角度1: %.2f°, 角度2: %.2f°, 角度3: %.2f°, 角度4: %.2f°",
//                    angle1, angle2, angle3, angle4
//            ));
        }

        if (nodeStates.get(0)) {
            actionLineView.setHeadPoint(getJointPosition(landmarks.get(0), playerId));
            actionLineView.setEyePoints(getJointPosition(landmarks.get(1), playerId), getJointPosition(landmarks.get(2), playerId));
        } else {
            actionLineView.setHeadPoint(null);
            actionLineView.setEyePoints(null, null);
        }
        actionLineView.setShoulders(getJointPosition(landmarks.get(11), playerId), getJointPosition(landmarks.get(12), playerId));
    }

    public void getNodeState() {
        for (Map.Entry<Integer, Boolean> entry : nodeStates.entrySet()) {
            int index = entry.getKey();
            boolean isEnabled = sharedPreferences.getBoolean(index + "", true);
            nodeStates.put(index, isEnabled);
        }
    }
    private PointF getJointPosition(NormalizedLandmark landmark, int playerId) {
        PlayerView playerView = null;
        if (playerId == 1) {
            playerView = playerView1;
        } else if (playerId == 2) {
            playerView = playerView2;
        }
        float offsetX = (playerView.getWidth() - playerView.getVideoSurfaceView().getWidth()) / 2;
        float offsetY = (playerView.getHeight() - playerView.getVideoSurfaceView().getHeight()) / 2;
        float x = offsetX + (landmark.x() * ((TextureView) playerView.getVideoSurfaceView()).getWidth());
        float y = offsetY + (landmark.y() *  ((TextureView) playerView.getVideoSurfaceView()).getHeight());
        return new PointF(x, y);
    }

    private List<PointF> convertLandmarkToJointPoints(List<NormalizedLandmark> landmarks, int playerId) {
        List<PointF> points = new ArrayList<>();
        // 遍历 nodeStates 中的键
        for (Map.Entry<Integer, Boolean> entry : nodeStates.entrySet()) {
            int index = entry.getKey();
            boolean isEnabled = entry.getValue();
            if (index == 0){
                continue;
            }
            // 检查节点状态是否为 true 且索引在 landmarks 列表范围内
            if (isEnabled) {
                NormalizedLandmark landmark = landmarks.get(index);
                points.add(getJointPosition(landmark, playerId));
            }
        }
        return points;
    }


    private List<PointF[]> convertLandmarkToLines(List<NormalizedLandmark> landmarks, int playerId) {
        List<PointF[]> lines = new ArrayList<>();
        int[][] connections = {
                {11, 12},
                {11, 13}, {13, 15},
                {12, 14}, {14, 16},
                {11, 23}, {12, 24},
                {23, 24}
        };

        for (int[] connection : connections) {
            int startIndex = connection[0];
            int endIndex = connection[1];
            if (nodeStates.get(startIndex) && nodeStates.get(endIndex)) {
                PointF startPoint = getJointPosition(landmarks.get(startIndex), playerId);
                PointF endPoint = getJointPosition(landmarks.get(endIndex), playerId);
                PointF[] line = new PointF[]{startPoint, endPoint};
                lines.add(line);
            }
        }
        return lines;
    }

    private List<PointF> convertLandmarkToPathPoints(List<NormalizedLandmark> landmarks, int playerId) {
        List<PointF> points = new ArrayList<>();
        for (int i : Utils.KEY_IDS) {
            if (nodeStates.get(i)) {
                NormalizedLandmark landmark = landmarks.get(i);
                points.add(getJointPosition(landmark, playerId));
            } else {
                points.add(null);
            }
        }
        return points;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacks(updateSeekBarRunnable);
        handler.removeCallbacks(checkSharedPrefsRunnable);
        player1.release();
        player2.release();
    }
}